home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
addpcx.zip
/
PCX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-06-21
|
11KB
|
476 lines
/* PCX.c - Graphic Routines that operate on PCX pictures
*/
#include <stdio.h>
#include "lib.h"
#include "pcx.h"
int pcx_init();
int pcx_clear();
int pcx_set_point();
int pcx_clr_point();
int pcx_xor_point();
int pcx_write_row();
int pcx_select_plane();
int pcx_set_palette();
int pcx_mode();
int movmem();
int pokeb();
int peekb();
int pcx_get_point();
static int (*pcx_func[])() = {
pcx_init, pcx_clear, pcx_set_point, pcx_clr_point,
pcx_xor_point, pcx_get_point, pcx_write_row, pcx_select_plane,
pcx_set_palette,pcx_mode, movmem, peekb, pokeb };
PCXPIC *pcx_cpic; /* current picture */
static int cplane; /* current plane */
int pcx_md; /* 1 if CGA-type picture, 0 for HERC/EGA */
int pcx_init()
{
movmem( pcx_func, vgr_func, sizeof(vgr_func) );
VGR_NBPL = VGR_HRES = VGR_VRES = VGR_NCOLORS = cplane = 0;
if ( pcx_cpic )
{ VGR_HRES = pcx_cpic->hdr.hres;
VGR_VRES = pcx_cpic->hdr.vres;
VGR_NBPL = pcx_cpic->hdr.bpl;
VGR_NCOLORS = pcx_cpic->hdr.bpp > 1 ?
0x01 << pcx_cpic->hdr.bpp :
0x01 << pcx_cpic->hdr.nplanes;
};
return OK;
}
int pcx_select_plane( plane )
int plane;
{
return cplane = plane & 0x03;
}
int pcx_write_row( row, prow, nbytes )
int nbytes, row;
char *prow;
{
int i;
i = pcx_cpic->hdr.hres / 8;
movmem( prow, (pcx_cpic->rows[cplane][row]),
nbytes <= i ? nbytes : i );
}
int pcx_clear()
{
int plane, row, nplanes, nrows, bytes;
nplanes = pcx_cpic->hdr.nplanes;
nrows = pcx_cpic->hdr.y2 - pcx_cpic->hdr.y1 +1;
bytes = pcx_cpic->hdr.bpl;
for ( plane=0; plane < nplanes; plane ++ )
for ( row=0; row < bytes; row++ )
setmem( (pcx_cpic->rows[plane][row]), bytes, 0 );
}
int pcx_mode( m )
int m;
{
switch ( m )
{ case MODE_APA0: /* 640x350x16 */
case MODE_APA1: /* 720x348x02 */
case MODE_APA2: /* 640x200x02 */
/* all these modes save color information
1 bit per plane.
*/
pcx_md = 0;
break;
case MODE_APA3: /* 320x200x04 */
/* this mode puts two bits per pixel into the
same plane.
*/
pcx_md = 1;
break;
default: /* invalid! */
return ERROR;
};
return OK;
}
int pcx_xor_point( x, y, color )
int x, y, color;
{
return pcx_set_point( x, y, pcx_get_point( x, y ) ^ color );
}
int pcx_clr_point( x, y )
int x, y;
{
return pcx_set_point( x, y, 0 );
}
int pcx_set_point( x, y, color )
int x, y, color;
{
register unsigned char *p;
unsigned char plane, b, o, mask;
if ( pcx_md )
{ o = (x & 3) << 1;
p = (unsigned char *)pcx_cpic->rows[0][y] + (x>>2);
*p = (*p & ~(0xc0 >> o)) | ((color & 0x03) << (6-o));
return OK;
};
o = x >> 3;
b = (unsigned int)0x80 >> (x & 0x07);
for ( mask=1,plane=0; plane < pcx_cpic->hdr.nplanes; plane++, mask<<=1 )
{ p = (unsigned char *)pcx_cpic->rows[plane][y] + o;
if ( color & mask )
*p |= b;
else *p &= ~b;
};
return OK;
}
int pcx_get_point( x, y )
int x, y;
{
unsigned char plane, b, o, color;
if ( pcx_md )
{ b = (x & 3) << 1;
return ( pcx_cpic->rows[0][y][x>>2] & (0xc0 >> b) ) >> (6-b);
};
o = x >> 3;
b = (unsigned int)0x80 >> (x & 0x07);
for ( color=plane=0; plane < pcx_cpic->hdr.nplanes; plane++ )
color |= !!(pcx_cpic->rows[plane][y][o] & b) << plane;
return color;
}
/* PCX Palette Settings.
*/
int pcx_set_palette( reg, red, green, blue )
unsigned char reg, red, green, blue;
{
if ( pcx_md )
{ pcx_cpic->hdr.triple[reg].red = red;
return OK;
};
/* why do we multiply by 85? */
pcx_cpic->hdr.triple[reg].red = red * 85;
pcx_cpic->hdr.triple[reg].green = green * 85;
pcx_cpic->hdr.triple[reg].blue = blue * 85;
return OK;
}
PCXPIC *pcx_init_pic( hres, vres, nplanes )
unsigned int hres, vres, nplanes;
{
int y, p, bpl;
PCXPIC *pic;
char *calloc();
static TRIPLET ega_pal[] = { /* copied from a */
0x00, 0x00, 0x00, /* PBRUSH picture file */
0x00, 0x00, 0xaa,
0x00, 0xaa, 0x00,
0x00, 0xaa, 0xaa,
0xaa, 0x00, 0x00,
0xaa, 0x00, 0xaa,
0xaa, 0xaa, 0x00,
0xaa, 0xaa, 0xaa,
0x55, 0x55, 0x55,
0x55, 0x55, 0xff,
0x55, 0xff, 0x55,
0x55, 0xff, 0xff,
0xff, 0x55, 0x55,
0xff, 0x55, 0xff,
0xff, 0xff, 0x55,
0xff, 0xff, 0xff };
static TRIPLET cga_pal[] = {
0,0,0, 255,0,0,
0,0,0, 255,0,0,
0,0,0, 255,0,0,
0,0,0, 255,0,0,
0,0,0, 255,0,0,
0,0,0, 255,0,0,
0,0,0, 255,0,0,
0,0,0, 255,0,0 };
if ( !(pic = (PCXPIC *) calloc( 1, sizeof(PCXPIC) )) )
return NULL; /* out of memory */
pic->hdr.x2 = hres -1;
pic->hdr.y2 = vres -1;
pic->hdr.maker = 10;
pic->hdr.version = 5;
pic->hdr.code = 1;
pic->hdr.bpp = 1 + pcx_md;
pic->hdr.bpl = bpl = (hres * (1+pcx_md)) / 8;
VGR_HRES = pic->hdr.hres = hres;
VGR_VRES = pic->hdr.vres = vres;
VGR_NBPL = bpl;
VGR_NCOLORS = 1 << (pic->hdr.nplanes = nplanes);
movmem( (pcx_md ? cga_pal : ega_pal),
pic->hdr.triple, sizeof(pic->hdr.triple) );
for ( p=0; p < nplanes; p++ )
{ if ( ! (pic->rows[p] = (uchar **)calloc( 1, sizeof(char *) * vres)) )
return pcx_free_pic( pic ), (PCXPIC *)0;
for ( y=0; y < vres; y++ )
if ( !(pic->rows[p][y] = (uchar *)calloc( 1, bpl )) )
return pcx_free_pic( pic ), (PCXPIC *)0;
};
return pic;
}
int pcx_free_pic( pic )
PCXPIC *pic;
{
int row, plane, nrows, nplan;
nrows = pic->hdr.y2 - pic->hdr.y1 +1;
nplan = pic->hdr.nplanes;
for ( plane = 0; plane < nplan; plane++ )
{ for ( row = 0; row < nrows; row++ )
allocf( pic->rows[plane][row] );
allocf( pic->rows[plane] );
};
allocf( pic );
return NULL;
}
void map_not( map, len )
register unsigned int *map, len;
{
for ( ; len--; map++ )
*map = ~ *map;
}
void pcx_invert_pic( pic )
PCXPIC *pic;
{
int p, r, i;
for ( p=0; p < pic->hdr.nplanes; p++ )
for ( r=0; r < (pic->hdr.y2 - pic->hdr.y1); r++ )
map_not( pic->rows[p][r], pic->hdr.bpl / 2 );
}
allocf( p )
char *p;
{
if ( !p )
return OK;
if ( free(p) == -1 )
CRASH( "heap munged" );
}
#ifdef MAIN
/* Manx 'C stack/heap size adjustment -
The vgr_fill() function uses an enourmous amount of stack,
and we're going to need enough heap space to allocate
4 bit maps for the EGA board.
*/
uint __STKLOW = 0,
__STKSIZ = 4096,
__HEAPSIZ = 8192;
int cga_init(), ega_init(), herc_init();
int board, (*board_init)(), md;
/* This structure is used here to facilitate drawing the
simple X and complex box that are used to test the
dot, line and fill functions.
*/
typedef struct {
int x,y;
} OBJ;
static OBJ obj[] = {
100, 100, 150, 200, 200, 100, 250, 150, 175, 250, 250, 350, 200, 400, 150, 300,
100, 400, 50, 350, 125, 250, 50, 150, 100, 100 };
static OBJ obj2[] = {
0, 0,280, 0,280,140,240,140,240, 20,200, 20,200,280,240,280,240,160,
280,160,280,300, 0,300, 0,160, 40,160, 40,280, 80,280, 80, 20, 40, 20,
40,140, 0,140, 0, 0 };
static OBJ obj3[] = {
120,20, 160,20, 160,280, 120,280, 120,20 };
main( argc, argv )
char **argv;
int argc;
{
void pcx_showpic();
FILE *fp, *fopen();
int c, h, v, p;
printf("PCX test routine.\n");
if ( argc == 1 )
printf("Try \"PCX xx\" for help\n" );
board = vgr_get_board();
if ( argc >= 2 )
{ if ( !strcmp(argv[1], "ega") )
board = TYPE_EGA;
else if ( !strcmp(argv[1], "cga") )
board = TYPE_CGA;
else if ( !strcmp(argv[1], "herc") )
board = TYPE_HERC;
else if ( !strcmp(argv[1], "cga2") )
board = 9;
else { printf("\
usage: PCX\n\
or PCX <board>\n\
or PCX <board> <pcx_file_name>\n\n\
func: Excercises the board & PCX routines.\n\
<board> may be one of:\n\
cga - 640x200x2 CGA\n\
cga2- 320x200x4 CGA\n\
herc- Hercules Hi-Res\n\
ega - 640x350x16 EGA\n\
<pcx_file_name> may be any file name,\n\
although an extension of .PCX is\n\
appropriate.\n" );
exit(1);
};
};
switch( board )
{ case TYPE_UNKNOWN:
case TYPE_MDA:
CRASH("unable to detect a HERC, CGA or EGA board");
case TYPE_CGA:
printf("CGA board detected\n");
board_init = cga_init;
md = MODE_APA2, c = 1, h = 640, v=200, p=1;
break;
case 9:
printf("CGA/APA3 Selected\n");
board_init = cga_init;
md = MODE_APA3, c = 2, h = 320, v=200, p=1;
break;
case TYPE_EGA:
printf("EGA board detected\n");
board_init = ega_init;
md = MODE_APA0, c = 9, h = 640, v=350, p=4;
break;
case TYPE_HERC:
printf("HERC board detected\n");
board_init = herc_init;
md = MODE_APA1, c = 1, h = 720, v=348, p=1;
break;
default:
CRASH("bug: invalid board type number");
};
printf("Hit return to continue:");
getchar();
/* pcx_init_pic needs to know what mode it's in
*/
pcx_init();
pcx_mode( md );
if ( !(pcx_cpic = pcx_init_pic( h, v, p )) )
CRASH("out of memory");
pcx_init();
if ( VGR_MODE( md ) )
CRASH( "error in mode selection" );
printf("HRES=%d, VRES=%d, NCOLORS=%d, NPLANES=%d, pcx_md=%d\n",
VGR_HRES, VGR_VRES, VGR_NCOLORS, p, pcx_md );
draw_it( (OBJ *)&obj, NELEMS(obj) , 3, 3, 0, 0, c );
printf(".");
draw_it( (OBJ *)&obj2, NELEMS(obj2), 3, 3, 150, 0, c );
printf(".");
draw_it( (OBJ *)&obj3, NELEMS(obj3), 3, 3, 150, 0, c );
printf(".");
vgr_fill( 33, 40, c );
printf(".");
vgr_fill( 179, 19, c );
printf("\nhit return to continue, then hit return again:");
getchar();
if ( (*board_init)() )
CRASH( "board init failed" );
if ( VGR_MODE( md ) )
CRASH( "error in mode selection" );
pcx_showpic( pcx_cpic, 0, 0, 0 );
getchar();
VGR_MODE( MODE_TEXT0 );
if ( argc == 3 )
{ if ( !(fp = fopen( argv[2], "w" )) )
CRASH( "error opening picture file" );
if ( pcx_write_pic( pcx_cpic, fp ) )
CRASH( "error writing picture file" );
fclose(fp);
};
exit(0);
}
draw_it( obj, n, divx, divy, ox, oy, c )
OBJ *obj;
int n, divx, divy;
{
int x;
vgr_point( obj[0].x / divx + ox, obj[0].y / divy + oy, -1 );
for ( x=1; x < n; x++ )
vgr_point( obj[x].x / divx + ox, obj[x].y / divy + oy, c );
}
#endif